package utils

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"io"
	mathRand "math/rand"
	"nav/global"
	"os"
	"strconv"
	"strings"
	"time"
)

// 判断所给路径文件/文件夹是否存在
func FileOrDirExists(path string) bool {
	_, err := os.Stat(path) //os.Stat获取文件信息
	if err != nil {
		if os.IsExist(err) {
			return true
		}
		return false
	}
	return true
}

// 解决json字符串整型精度缺失
func PrecisionLost(data interface{}) (map[string]interface{}, error) {
	bdata, err := json.Marshal(data)
	if err != nil {
		return nil, err
	}
	var val map[string]interface{}
	d := json.NewDecoder(bytes.NewBuffer(bdata))
	d.UseNumber()
	err = d.Decode(&val)
	if err != nil {
		return nil, err
	}
	return val, nil
}

// 反序列化request.body中的json数据为map
func GetBodyData(ctx *gin.Context) (map[string]interface{}, error) {
	bdata := make([]byte, 1024)
	length, err := ctx.Request.Body.Read(bdata)
	if err != nil && err != io.EOF {
		return nil, err
	}
	var data map[string]interface{}
	str := string(bdata[:length])
	decoder := json.NewDecoder(strings.NewReader(str))
	decoder.UseNumber()
	err1 := decoder.Decode(&data)
	if err1 != nil {
		return nil, err
	}
	return data, nil
}

// 构建文件url连接主机端口全链接 "https://192.168.11.121:7889/meida/upload/..."
func BuildAbsoluteUri(ctx *gin.Context, filePath string) string {
	host := ctx.Request.Host
	schema := ctx.Request.Header.Get("X-Forwarded-Proto")
	if schema == "https" {
		return fmt.Sprintf("https://%s/%s", host, filePath)
	} else {
		return fmt.Sprintf("http://%s/%s", host, filePath)
	}
}

// 字符串转uint64
func StrtoUint64(s string) uint64 {
	intNum, _ := strconv.Atoi(s)
	return uint64(intNum)
}

// 字符串转int
func Strtoint(s string) int {
	intNum, _ := strconv.Atoi(s)
	return int(intNum)
}

// 字符串转int64
func Strtoint64(s string) int64 {
	intNum, _ := strconv.ParseInt(s, 10, 64)
	return intNum
}

//生成32位md5字串
func GetMd5String(s string) string {
	h := md5.New()
	h.Write([]byte(s))
	return hex.EncodeToString(h.Sum(nil))
}

//生成Guid字串
func UniqueId() string {
	b := make([]byte, 48)

	if _, err := io.ReadFull(rand.Reader, b); err != nil {
		return ""
	}
	return GetMd5String(base64.URLEncoding.EncodeToString(b))
}

// int64转 int
func Int64ToInt(num int64) (intNum int) {
	intNum, err := strconv.Atoi(strconv.FormatInt(num, 10))
	if err != nil {
		fmt.Errorf("int64转 int=>" + err.Error())
		return 0
	}
	return
}
func StrToUint(str string) uint {
	i, e := strconv.Atoi(str)
	if e != nil {
		return 0
	}
	return uint(i)
}

// 计算总页数
func CalcTotalPage(total int, pageSize int) (totalPage int) {
	totalPage = total / pageSize
	if total%pageSize != 0 {
		totalPage += 1
	}
	return
}

// 处理获取的分页参数
func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {

	if pageSize == 0 {
		pageSize = global.NLY_CONFIG.System.PageSize
	}
	return func(db *gorm.DB) *gorm.DB {
		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

// 处理查询创建时间范围
func QueryCreated(startTime uint, endTime uint) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if startTime != 0 {
			db.Where("created >= (?)", startTime)
		}
		if endTime != 0 {
			db.Where("created =< (?)", endTime)
		}
		return db
	}
}

func getTimeTick64() int64 {
	return time.Now().UnixNano() / 1e6
}

func getFormatTime(time time.Time) string {
	return time.Format("20060102")
}

/**
生成订单编号:日期20191025时间戳1571987125435+3位随机数
*/
func GenerateOrderNum() string {
	date := getFormatTime(time.Now())
	r := mathRand.Intn(100)
	return date + strconv.FormatInt(getTimeTick64(), 10) + strconv.Itoa(r)
}
